#include "rtspsession.h"
#include <QDebug>
//#include <QtEndian>  // 必须添加的头文件
#include <QByteArray>
#include <QDataStream>
#include "rtpsender.h"

//要打开的h264文件
#define FILE_NAME "test2.264"

RtspSession::RtspSession(QTcpSocket *socket, QObject *parent)
    : QObject(parent), m_socket(socket)
{
    connect(m_socket, &QTcpSocket::readyRead, this, &RtspSession::readClient);
}

//处理客户端RTSP请求
void RtspSession::readClient()
{
    QByteArray data = m_socket->readAll();

    qInfo() << "readClient:";
    qInfo() << data;

    // 处理RTSP命令
    if (data.startsWith("OPTIONS"))
    {
        int cseqPos = data.indexOf("CSeq:");
        int cseqEnd = data.indexOf("\r\n", cseqPos);
        QByteArray cseqValue = data.mid(cseqPos+5, cseqEnd-(cseqPos+5)).trimmed();

        // 构建完整响应
        QByteArray response = "RTSP/1.0 200 OK\r\n"
                              "CSeq: " + cseqValue + "\r\n"
                              "Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE\r\n"
                              "Server: QtRTSP/1.0\r\n\r\n";

        qInfo() << "OPTIONS response:";
        qInfo() << response;
        m_socket->write(response);
    }
    else if (data.startsWith("DESCRIBE"))
    {
        //客户端请求
        //DESCRIBE rtsp://127.0.0.1:554 RTSP/1.0\r\n
        //CSeq: 3\r\n
        //User-Agent: LibVLC/3.0.21 (LIVE555 Streaming Media v2016.11.28)\r\n
        //Accept: application/sdp\r\n

        int cseqPos = data.indexOf("CSeq:");
        int cseqEnd = data.indexOf("\r\n", cseqPos);
        QByteArray cseqValue = data.mid(cseqPos+5, cseqEnd-(cseqPos+5)).trimmed();

        QByteArray sdp = "v=0\r\n"
                         "o=- 123456 1 IN IP4 127.0.0.1\r\n"
                         "m=video 0 RTP/AVP 96\r\n"
                         "a=rtpmap:96 H264/90000\r\n"
                         "a=fmtp:96 packetization-mode=1\r\n"
                         "a=control:track1\r\n";

        //*不指定a=control轨道标识可能会导致协议兼容性问题‌
        //服务器返回SDP（Session Description Protocol）格式的响应，包含媒体类型（如视频H.264）、传输协议（RTP/UDP或RTP/TCP）及编码参数
        // RTP/AVP 表示使用‌RTPoverUDP‌，这是RTSP默认的传输方式
        //若需显式指定TCP传输，需在a=control或Transport头中添加RTP/AVP/TCP参数

        QByteArray response = "RTSP/1.0 200 OK\r\n"
                              "CSeq: " + cseqValue + "\r\n"
                              "Content-Type: application/sdp\r\n"
                              "Content-Length: " + QByteArray::number(sdp.size()) + "\r\n\r\n" + sdp;

        qInfo() << "DESCRIBE response:";
        qInfo() << response;

        m_socket->write(response);
    }
    else if (data.startsWith("SETUP"))
    {
        //客户端请求
        //SETUP rtsp://127.0.0.1:8080/ RTSP/1.0\r\n
        //CSeq: 4\r\n
        //User-Agent: LibVLC/3.0.21 (LIVE555 Streaming Media v2016.11.28)\r\n
        //Transport: RTP/AVP;unicast;client_port=61786-61787\r\n\r\n"

        //*client_port 这里提议了建立连接的端口, 服务器返回 200 OK，即‌接受提议‌，后面RTP数据传输使用指定的端口
        //*返回 Session 给客户端,表明连接建立完成，会话初始化成功,这里指定为 12345678
        //*Session: 12345678 需要server指定，在SETUP请求建立传输通道时返回给客户端

        int cseqPos = data.indexOf("CSeq:");
        int cseqEnd = data.indexOf("\r\n", cseqPos);
        QByteArray cseqValue = data.mid(cseqPos+5, cseqEnd-(cseqPos+5)).trimmed();

        //设置约定的端口
        //server_port：服务器发送RTP/RTCP数据的端口（如5000-5001）
        //client_port：确认使用客户端提议的端口（61786-61787）
        //双向端口绑定要求‌，RTSP规范要求SETUP响应必须明确返回server_port参数，
        //用于标识服务器端绑定的RTP/RTCP端口对（偶数端口为RTP，相邻奇数端口为RTCP）

        //从请求获取client_port的两个端口，相邻两个端口一偶数一奇数，偶数用于RTP传输，奇数用于RTCP
        QString strdata(data);
        parseClientPort(strdata);
        //指定server发送RTP/RTCP的两个端口，相邻两个端口一偶数一奇数，偶数用于RTP传输，奇数用于RTCP
        m_serverport1 = 9000;
        m_serverport2 = 9001;

        QString strclientport1 = QString::number(m_clientport1);
        QString strclientport2 = QString::number(m_clientport2);
        QString strserverport1 = QString::number(m_serverport1);
        QString strserverport2 = QString::number(m_serverport2);

        QByteArray strclient_port = "client_port=" + strclientport1.toUtf8() + "-" + strclientport2.toUtf8() + ";" ;
        QByteArray strserver_port = "server_port=" + strserverport1.toUtf8() + "-" + strserverport2.toUtf8() + ";";
        QByteArray response = "RTSP/1.0 200 OK\r\n"
                              "CSeq: " + cseqValue + "\r\n"
                              "Transport: RTP/AVP;unicast;"+ strclient_port + strserver_port  +"\r\n"
                              "Session: 12345678\r\n\r\n";

        qInfo() << "SETUP response:";
        qInfo() << response;
        m_socket->write(response);

    }
    else if (data.startsWith("PLAY"))
    {
        //客户端请求
        // PLAY rtsp://127.0.0.1:8080 RTSP/1.0\r\n
        // CSeq: 5\r\n
        // User-Agent: LibVLC/3.0.21 (LIVE555 Streaming Media v2016.11.28)\r\n
        // Session: 12345678\r\n
        // Range: npt=0.000-\r\n\r\n

        int cseqPos = data.indexOf("CSeq:");
        int cseqEnd = data.indexOf("\r\n", cseqPos);
        QByteArray cseqValue = data.mid(cseqPos+5, cseqEnd-(cseqPos+5)).trimmed();
        QByteArray response = "RTSP/1.0 200 OK\r\n"
                              "CSeq: " + cseqValue + "\r\n"
                              "Session: 12345678\r\n"
                              "Range: npt=0.000-\r\n"
                              "RTP-Info: url=rtsp://127.0.0.1:554/track1;seq=0\r\n"
                              "\r\n";

        //*RTP-Info头‌：明确媒体流信息（如URL和初始序列号），这是PLAY响应中最重要的字段，用于指导后续RTP传输

        qInfo() << "PLAY response:";
        qInfo() << response;
        m_socket->write(response);

        //创建RtpSender，发送数据, 必须先回复"PLAY"再发送数据
        //服务器开始向协商好的端口（server_port→client_port）发送RTP数据
        RtpSender* sender = new RtpSender(m_clientport1, m_serverport1, FILE_NAME);
        sender->start();
    }
    else if(data.startsWith("SET_PARAMETER"))
    {

    }
    else if(data.startsWith("TEARDOWN"))
    {
        int cseqPos = data.indexOf("CSeq:");
        int sessionPos = data.indexOf("Session:");
        QByteArray cseq = data.mid(cseqPos + 5, data.indexOf("\r\n", cseqPos) - (cseqPos + 5)).trimmed();
        QByteArray sessionId = data.mid(sessionPos + 8, data.indexOf("\r\n", sessionPos) - (sessionPos + 8)).trimmed();

        // 发送响应
        QByteArray response = "RTSP/1.0 200 OK\r\n"
                              "CSeq: " + cseq + "\r\n"
                              "Session: " + sessionId + "\r\n\r\n";

        qInfo() << "TEARDOWN response:";
        qInfo() << response;
        m_socket->write(response);

        // 释放资源（如关闭RTP通道、清除会话状态）
        //releaseSessionResources(sessionId);
    }
    else if(data.startsWith("PAUSE"))
    {

    }
}

//从请求中获取client_port，并缓存
void RtspSession::parseClientPort(const QString &rtspHeader)
{
    // 查找Transport行
    int transportPos = rtspHeader.indexOf("Transport:");
    if (transportPos == -1)
    {
        qWarning() << "Transport header not found";
        return;
    }

    // 提取client_port=后面的部分
    int clientPos = rtspHeader.indexOf("client_port=", transportPos);
    if (clientPos == -1)
    {
        qWarning() << "client_port attribute not found";
        return;
    }

    QString portStr = rtspHeader.mid(clientPos + 12); // 跳过client_port=前缀
    int hyphenPos = portStr.indexOf('-');
    if (hyphenPos == -1)
    {
        qWarning() << "Invalid port format (missing hyphen)";
        return;
    }

    QString port1Str = portStr.left(hyphenPos);
    QString port2Str = portStr.mid(hyphenPos + 1);

    // 转换为整数
    bool ok1, ok2;
    m_clientport1 = port1Str.toUShort(&ok1);
    m_clientport2 = port2Str.toUShort(&ok2);

    if (ok1 && ok2)
    {
        qDebug() << "Extracted ports:" << m_clientport1 << "and" << m_clientport2;
    }
    else
    {
        qWarning() << "Invalid port numbers";
    }
}

